// Copyright (c) 2010 god6or@gmail.com under MIT license.

package ul.ownet

import java.io.{File, FileOutputStream, FileInputStream}
import java.sql.{DriverManager, Connection, Statement, ResultSet}
import collection.mutable.{ArrayBuffer}

class DB {

    //Class.forName("org.sqlite.JDBC")
    //var db: Connection = null
    //var st: Statement = null
    
    object DBRow {
        val fieldNAmes = List("time","stype","serial","name","t")
        val fieldTypes = List("TIMESTAMP","SMALLINT","CHAR(12)","VARCHAR(20)","FLOAT")
        def fromCSV( csv: String ): DBRow = {
            val csvs = csv.split(";")
            new DBRow( csvs(0).toLong, csvs(1).toInt, csvs(2).toLong, csvs(3), csvs(4).toDouble )
        }
    }
    class DBRow (
        val time:   Long,   // absolute timestamp, milliseconds
        val stype:  Int,    // sensor type
        val serial: Long,   // sensor serial
        val name:   String, // sensor name
        val t:      Double  // temperature (NaN if error)
    ) {
        def toCSV = "" + time + ";" + stype + ";" + serial + ";" + name + ";" + t
    }
    
    val rows = ArrayBuffer[DBRow]() // DB rows
    def size = rows.length // returns number of records in db
    var lastSize = 0
    var newStart = true
    def clear = {
        rows.clear // clears db
        lastSize = 0
        newStart = true
    }
    def add( s: Sensor ) = { // adds new sensor measurement
        //println("Before add: " + s.temperature + ", " + s.sensor.temperature + ", " + s.lastTemperature)
        if ((!s.temperature.isNaN) && ((s.sensor.temperature != 85.0) ||
            ((s.sensor.temperature == 85.0) && (!s.lastTemperature.isNaN) &&
             ((s.lastTemperature - s.sensor.temperature) < 5.0)))) {
            rows += new DBRow( System.currentTimeMillis(), s.typeCode,
                s.serialNumber, s.name, s.temperature )
        }
    }
    // returns list of sensors serial numbers present in DB
    def serials: List[Long] = {
        val sns = new ArrayBuffer[Long]
        for (row <- rows if !sns.contains(row.serial)) sns += row.serial
        sns.toList
    }
    // returns list of sensors names (corresponding to serial numbers returned by serials function)
    def names: List[String] = {
        val sns = serials
        val ns:Array[String] = (for (sn <- sns) yield format("%012X", sn)).toArray
        for (row <- rows) ns(sns.indexOf(row.serial)) = row.name
        ns.toList
    }

    def toCSV( fName: String ): Boolean = { // export records to CSV file
        var success = false
        try {
            val fo = new FileOutputStream(fName)
            for (row <- rows) {
                for (b <- (row.toCSV + "\n").getBytes("utf8")) fo.write(b.toByte)
            }
            fo.close()
            success = true
        } catch { case _ => println("*Error: Can't write CSV file " + fName)}
        success
    }
    def fromCSV( fName: String ): Boolean = { // import records from CSV file
        var success = false
        try {
            val fi = new FileInputStream(fName)
            val line = new ArrayBuffer[Byte]
            while (fi.available() > 0) {
                val b = fi.read()
                if (b != 10) line += b.toByte
                else {
                    try { rows += DBRow.fromCSV(new String( line.toArray, "utf8" ))
                    } catch { case _ => }
                    line.clear
                }
            }
            fi.close()
            success = true
        } catch { case _ => println("*Error: Can't write CSV file " + fName)}
        success
    }

    def open = {
        
        /*val dbExists = new File(Config.dbName).isFile
        db = DriverManager.getConnection("jdbc:sqlite:" + Config.dbName)
        
        st = db.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT )
        
        // create new table
        if (!dbExists) {
            println("\n" + "** Creating database... \n")
            st.execute("CREATE TABLE log ( " +
            "id INT PRIMARY KEY, date DATETIME, type SMALLINT, serial CHAR(12), name VARCHAR(20), t FLOAT" +
            " )"
            )
        }*/
    }
    def close = {
        //db.close()
    }

}

